package com.piggy.logi.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.piggy.common.core.constant.SecurityConstants;
import com.piggy.common.core.domain.R;
import com.piggy.common.core.utils.FeignResultUtils;
import com.piggy.common.core.utils.PageUtils;
import com.piggy.common.core.web.page.PagePlus;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.logi.sys.bo.LogiCarrierDriverLineEditBo;
import com.piggy.logi.sys.bo.LogiCarrierDriverLineQueryBo;
import com.piggy.logi.sys.domain.LogiCarrierDriverLine;
import com.piggy.logi.sys.mapper.LogiCarrierDriverLineMapper;
import com.piggy.logi.sys.service.ILogiCarrierDriverLineService;
import com.piggy.logi.sys.vo.LogiCarrierDriverLineExtVo;
import com.piggy.sys.api.RemoteDistrictService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 常用线路管理Service业务层处理
 */
@Slf4j
@Service
public class LogiCarrierDriverLineServiceImpl extends ServiceImpl<LogiCarrierDriverLineMapper, LogiCarrierDriverLine> implements ILogiCarrierDriverLineService {

    @Resource
    private RemoteDistrictService districtService;

    @Override
    public LogiCarrierDriverLineExtVo queryById(String id) {
        LogiCarrierDriverLineExtVo vo = getVoById(id, LogiCarrierDriverLineExtVo.class);
        if (ObjectUtil.isEmpty(vo)) {
            return vo;
        }

        return fillData(Lists.newArrayList(vo)).get(0);
    }

    @Override
    public TableDataInfo<LogiCarrierDriverLineExtVo> queryPageList(LogiCarrierDriverLineQueryBo bo) {
        PagePlus<LogiCarrierDriverLine, LogiCarrierDriverLineExtVo> result = pageVo(PageUtils.buildPagePlus(bo, true), buildQueryWrapper(bo), LogiCarrierDriverLineExtVo.class);
        result.setRecordsVo(fillData(result.getRecordsVo()));
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<LogiCarrierDriverLineExtVo> queryList(LogiCarrierDriverLineQueryBo bo) {
        return fillData(listVo(buildQueryWrapper(bo), LogiCarrierDriverLineExtVo.class));
    }

    private LambdaQueryWrapper<LogiCarrierDriverLine> buildQueryWrapper(LogiCarrierDriverLineQueryBo bo) {
        LambdaQueryWrapper<LogiCarrierDriverLine> lqw = Wrappers.lambdaQuery();
        lqw.eq(StrUtil.isNotBlank(bo.getId()), LogiCarrierDriverLine::getId, bo.getId());
        lqw.eq(bo.getCarrierDriverId() != null, LogiCarrierDriverLine::getCarrierDriverId, bo.getCarrierDriverId());
        lqw.eq(bo.getDepartDistrict() != null, LogiCarrierDriverLine::getDepartDistrict, bo.getDepartDistrict());
        lqw.eq(bo.getArriveDistrict() != null, LogiCarrierDriverLine::getArriveDistrict, bo.getArriveDistrict());
        lqw.eq(bo.getLineType() != null, LogiCarrierDriverLine::getLineType, bo.getLineType());
        lqw.in(CollUtil.isNotEmpty(bo.getCarrierDriverIds()), LogiCarrierDriverLine::getCarrierDriverId, bo.getCarrierDriverIds());
        return lqw;
    }

    public List<LogiCarrierDriverLineExtVo> fillData(List<LogiCarrierDriverLineExtVo> extVos) {

        List<String> distIds = extVos.stream().map(vo -> vo.getDepartDistrict().toString()).distinct().collect(Collectors.toList());
        distIds.addAll(extVos.stream().map(vo -> vo.getArriveDistrict().toString()).distinct().collect(Collectors.toList()));
        distIds.add("-1");

        R<Map<String, String>> distMapR = districtService.getDistrictMap(distIds, SecurityConstants.INNER);
        FeignResultUtils.throwIfFailed(distMapR);

        extVos.stream().peek(Any -> {
            Any.setArriveDistrictName(ObjectUtil.defaultIfNull(distMapR.getData(), new HashMap<String, String>()).get(Any.getArriveDistrict().toString()));
            Any.setDepartDistrictName(ObjectUtil.defaultIfNull(distMapR.getData(), new HashMap<String, String>()).get(Any.getDepartDistrict().toString()));
        }).collect(Collectors.toList());

        return Lists.newArrayList(extVos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByAddBo(LogiCarrierDriverLineEditBo bo) {
        LogiCarrierDriverLine add = BeanUtil.toBean(bo, LogiCarrierDriverLine.class);
        return save(add);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByEditBo(LogiCarrierDriverLineEditBo bo) {
        LogiCarrierDriverLine update = BeanUtil.toBean(bo, LogiCarrierDriverLine.class);
        return updateById(update);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchByAddBo(List<LogiCarrierDriverLineEditBo> boList) {
        if (CollUtil.isEmpty(boList)) {
            return false;
        }

        boList.forEach(this::insertByAddBo);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchByUpdateBo(List<LogiCarrierDriverLineEditBo> boList) {
        if (CollUtil.isEmpty(boList)) {
            return false;
        }

        boList.forEach(this::updateByEditBo);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateByDriverId(Long driverId, Integer lineType, List<LogiCarrierDriverLineEditBo> boList) {
        if (CollUtil.isEmpty(boList)) {
            baseMapper.removeByDriverId(driverId, lineType);
        } else {
            List<LogiCarrierDriverLine> listDb = baseMapper.selectByDriverIds(Lists.newArrayList(driverId), lineType);

            List<LogiCarrierDriverLine> updates = BeanUtil.copyToList(boList.stream().filter(item -> item.getId() != null)
                    .collect(Collectors.toList()), LogiCarrierDriverLine.class);
            Set<Long> updateIds = updates.stream().map(LogiCarrierDriverLine::getId).collect(Collectors.toSet());
            List<LogiCarrierDriverLine> adds = BeanUtil.copyToList(boList.stream().filter(item -> item.getId() == null)
                    .collect(Collectors.toList()), LogiCarrierDriverLine.class);
            List<Long> removeIds = listDb.stream().map(LogiCarrierDriverLine::getId)
                    .filter(id -> !updateIds.contains(id)).distinct().collect(Collectors.toList());

            this.updateBatchById(updates);
            this.saveBatch(adds);
            this.removeBatchByIds(removeIds);
        }
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }
}
